package com.qf.hospital.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.hospital.constants.HospitalConstants;
import com.qf.hospital.entity.SysMenu;
import com.qf.hospital.entity.SysRole;
import com.qf.hospital.entity.SysUser;
import com.qf.hospital.entity.SysUserExample;
import com.qf.hospital.enums.HospitalExceptionEnums;
import com.qf.hospital.exception.HospitalException;
import com.qf.hospital.mapper.SysUserMapper;
import com.qf.hospital.realm.HospitalRealm;
import com.qf.hospital.service.SysRoleService;
import com.qf.hospital.service.SysUserService;
import com.qf.hospital.utils.ExampleUtil;
import com.qf.hospital.vo.SideVO;
import com.qf.hospital.vo.UserRoleVO;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author ASUS
 * @version V1.0
 * @Project hospital
 * @Package com.qf.hospital.service.impl
 * @Date 2021/10/15 11:44
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    private final String INIT_PASSWORD = "123456789abc!";

    Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 根据用户名查询用户信息
     * @param loginName
     * @return
     */
    @Override
    public SysUser findByLoginName(String loginName) {
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria().andLoginNameEqualTo(loginName);
        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        if(sysUsers != null && sysUsers.size() == 1){
            SysUser sysUser = sysUsers.get(0);
            if(sysUser.getAvailable() == 0){
                //用户已经失效
                log.error("【登录功能】 用户已经失效，请联系管理员！");
                throw new HospitalException(HospitalExceptionEnums.USER_HAS_EXPIRED);
            }
            return sysUser;
        }
        return null;
    }

    /**
     * 根据用户id查询菜单信息
     * @param userId
     * @return
     */
    @Override
    public List<SideVO> findMenuByUserId(Integer userId) {
        List<SideVO> result = new ArrayList<>();
        HashMap<Integer, SideVO> map = new HashMap<>();

        List<SysMenu> menuByUserId = sysUserMapper.findMenuByUserId(userId);
        ListIterator<SysMenu> sysMenuListIterator = menuByUserId.listIterator();
        while (sysMenuListIterator.hasNext()){
            SysMenu sysMenu = sysMenuListIterator.next();
            if(sysMenu.getParentId() == 1){
                //一级菜单
                SideVO sideVO = new SideVO();
                BeanUtils.copyProperties(sysMenu,sideVO);
                map.put(sysMenu.getId(),sideVO);
                sysMenuListIterator.remove();
            }
        }
        for (SysMenu sysMenu : menuByUserId) {
            SideVO parentVO = map.get(sysMenu.getParentId());
            if(parentVO != null){
                SideVO sideVO = new SideVO();
                BeanUtils.copyProperties(sysMenu,sideVO);
                parentVO.getChildren().add(sideVO);
            }
        }
        for (Map.Entry<Integer, SideVO> integerSideVOEntry : map.entrySet()) {
            result.add(integerSideVOEntry.getValue());
        }
        return result;
    }

    /**
     * 根据条件查询用户信息
     * @param realname
     * @param loginname
     * @param identity
     * @param phone
     * @param address
     * @param page
     * @param limit
     * @return PageInfo<SysUser>
     */
    @Override
    public PageInfo<SysUser> selectAllUser(String realname, String loginname, String identity, String phone, String address, Integer page, Integer limit) {
        //1、执行分页
        PageHelper.startPage(page,limit);
        //2、封装查询条件
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        //2.1 真实姓名
        if(!StringUtils.isEmpty(realname)){
            criteria.andRealNameLike(ExampleUtil.any(realname));
        }
        //2.2 登录名
        if(!StringUtils.isEmpty(loginname)){
            criteria.andLoginNameLike(ExampleUtil.any(loginname));
        }
        //2.3 地址
        if(!StringUtils.isEmpty(address)){
            criteria.andAddressLike(ExampleUtil.any(address));
        }
        //2.4 手机号
        if(!StringUtils.isEmpty(phone)){
            criteria.andPhoneLike(ExampleUtil.any(phone));
        }
        //2.5 身份证
        if(!StringUtils.isEmpty(identity)){
            criteria.andIdentityLike(ExampleUtil.any(identity));
        }
        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        PageInfo<SysUser> pageInfo = new PageInfo<>(sysUsers);
        return pageInfo;
    }

    /**
     * 添加用户
     * @param sysUser
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void add(SysUser sysUser) {
        String salt = UUID.randomUUID().toString();
        String pwd = new Md5Hash(INIT_PASSWORD, salt, HospitalRealm.HASH_ITERATIONS).toString();
        int type = HospitalConstants.USER_TYPE_SYSTEM;
        sysUser.setSalt(salt);
        sysUser.setPwd(pwd);
        sysUser.setType(type);
        int count = sysUserMapper.insertSelective(sysUser);
        if(count != 1){
            log.error("【添加用户信息】 添加失败！sysUser={}",sysUser);
            throw new HospitalException(HospitalExceptionEnums.USER_ADD_ERROR);
        }
    }

    /**
     * 修改用户
     * @param sysUser
     */
    @Override
    public void update(SysUser sysUser) {
        int count = sysUserMapper.updateByPrimaryKeySelective(sysUser);
        if(count != 1){
            log.error("【修改用户信息】 修改失败！sysUser={}",sysUser);
            throw new HospitalException(HospitalExceptionEnums.USER_UPDATE_ERROR);
        }
    }

    /**
     * 展示分配角色信息
     * @param userid
     * @return
     */
    @Override
    public List<UserRoleVO> initUserRole(Integer userid) {
        List<SysRole> sysRoleList = sysRoleService.findAll();
        List<Integer> userRoleId = sysUserMapper.findRoleIdByUserId(userid);
        List<UserRoleVO> data = new ArrayList<>();
        for (SysRole sysRole : sysRoleList) {
            UserRoleVO userRoleVO = new UserRoleVO();
            BeanUtils.copyProperties(sysRole,userRoleVO);
            if(userRoleId.contains(userRoleVO.getRoleId())){
                userRoleVO.setLayChecked(true);
            }
            data.add(userRoleVO);
        }
        return data;
    }

    /**
     * 分配角色信息
     * @param userid
     * @param ids
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveUserRole(Integer userid, Integer[] ids) {
        //1、先删除
        sysUserMapper.deleteUserRoleByUserId(userid);
        //2、再添加
        if(ids != null && ids.length > 0){
            int count = sysUserMapper.saveUserRole(userid,ids);
            if(count != ids.length){
                log.error("【分配角色信息】 分配角色信息失败！ userId = {}，roleIds = {}",userid,Arrays.toString(ids));
                throw new HospitalException(HospitalExceptionEnums.USER_SAVE_USER_ROLE_ERROR);
            }
        }
    }

    /**
     * 删除角色，假删除，使用户变为不可用状态
     * @param userid
     */
    @Override
    public void deleteUser(Integer userid) {
        int count = sysUserMapper.deleteUserByUserId(userid);
        if(count != 1){
            log.error("【删除角色信息】 删除角色信息失败！ userId = {}，roleIds = {}",userid);
            throw new HospitalException(HospitalExceptionEnums.USER_DELETE_ERROR);
        }
    }

    /**
     * 重置密码
     * @param userid
     */
    @Override
    public void resetUserPwd(Integer userid) {
        String pwd = new Md5Hash(INIT_PASSWORD, UUID.randomUUID().toString(), HospitalRealm.HASH_ITERATIONS).toString();
        int count = sysUserMapper.resetUserPwd(userid,pwd);
        if(count != 1){
            log.error("【重置密码】 重置失败！ userId = {}，roleIds = {}",userid);
            throw new HospitalException(HospitalExceptionEnums.PASSWORD_RESET_FAILED);
        }
    }


}
